<?php
// +----------------------------------------------------------------------
// | 数据库管理
// +----------------------------------------------------------------------
// | @link ( http://www.yurnero.net )
// +----------------------------------------------------------------------
// | @copyright
// +----------------------------------------------------------------------
// | @licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | @author Haijun Wu <nicholasinlove@126.com>
// +----------------------------------------------------------------------
// | $Id: BakAction.class.php 109 2011-05-06 08:21:00Z nicholasinlove1986@gmail.com $
// +----------------------------------------------------------------------


class BakAction extends BaseAction {
	
	public function index() {
		redirect(__APP__);
	}
	
	//备份页面
	public function backup() {	
		//$this->checkLimits();	
		/* 检查目录权限 */
		$path = ROOT_PATH . DATA_DIR . '/Sqldata';
		$mask = file_mode_info($path);
		if ($mask === false) {
			$warning = sprintf(L('dir_not_exist'), $path);
			$this->assign('warning', $warning);
		} elseif ($mask != 15) {
			$warning = sprintf(L('dir_priv'), $path) . '<br/>';
			if (($mask&1) < 1) {
				$warning .= L('cannot_read') . '&nbsp;&nbsp;';
			}
			if (($mask&2) < 1) {
				$warning .= L('cannot_write') . '&nbsp;&nbsp;';
			}
			if (($mask&4) < 1) {
				$warning .= L('cannot_add') . '&nbsp;&nbsp;';
			}
			if (($mask&8) < 1) {
				$warning .= L('cannot_modify');
			}
			$this->assign('warning', $warning);
		}
		
		//获取最大上传限制
		$allow_max_size = return_bytes(@ini_get('upload_max_filesize')); // 单位为字节
		$allow_max_size = $allow_max_size / 1024; // 转换单位为 KB
		
		$table = $this->getTables();
		
		$this->assign('action_link', array('href'=>__URL__.'/restore/', 'text' => L('restore')));
		$this->assign('ur_here',L('backup'));
		$this->assign('file_name', get_random_name().'.sql');
		$this->assign('vol_size', $allow_max_size);
		$this->assign('table', $table);
		$this->display();
	}
	
	//备份处理
	public function dumpSql() {	
		$this->checkLimits();
		if ($_REQUEST['dumpsql']) {		
			/* 检查目录权限 */
			$path = ROOT_PATH . DATA_DIR . '/Sqldata';
			$mask = file_mode_info($path);
			if ($mask === false) {
				$warning = sprintf(L('dir_not_exist'), $path);
				$this->error ($warning);
			} elseif ($mask != 15) {
				$warning = sprintf(L('dir_priv'), $path);
				if (($mask&1) < 1) {
				$warning .= L('cannot_read') . '&nbsp;&nbsp;';
				}
				if (($mask&2) < 1) {
					$warning .= L('cannot_write') . '&nbsp;&nbsp;';
				}
				if (($mask&4) < 1) {
					$warning .= L('cannot_add') . '&nbsp;&nbsp;';
				}
				if (($mask&8) < 1) {
					$warning .= L('cannot_modify');
				}
				$this->error ($warning);
			}
				
			import("@.ORG.Sql");	
			$dump = new Sql ();
			
			$max_size = empty($_REQUEST['vol_size']) ? 0 : intval($_REQUEST['vol_size']);
			
			/* 变量验证 */
			$allow_max_size = intval(@ini_get('upload_max_filesize')); //单位M
			if ($allow_max_size > 0 && $max_size > ($allow_max_size * 1024)) {
				$max_size = $allow_max_size * 1024; //单位K
			}
		
			if ($max_size > 0) {
				$max_size = $max_size * 1024;
			}
			
			/* 初始化备份数据表*/
			if (empty($_REQUEST['customtables'])) {
				$tables  =  $this->getTables();
			} else {
				$tables  =  $_REQUEST['customtables'];
			}
			
			/* 初始化输入变量 */
			if (empty($_REQUEST['file_name'])) {
				$file_name = $dump->get_random_name();
			} else {
				$file_name = str_replace("0xa", '', trim($_REQUEST['file_name'])); // 过滤 0xa 非法字符
				$pos = strpos($file_name, '.sql');
				if ($pos !== false) {
					$file_name = substr($file_name, 0, $pos);
				}
			}
	
			if ($dump->dumpTable($path,$file_name,$tables,$max_size)) {
				set_log('backup(Sql)');
				$this->assign('jumpUrl',__URL__.'/restore/');
				$this->success (L('success'));
			} else {
				$this->error (L('error'));
			}	
		} else {
			$this->error (L('illegal'));
		}	
	}
	
	//数据恢复页面
	public function restore() {	
		//$this->checkLimits();	
		/* 检查目录权限 */
		$path = ROOT_PATH . DATA_DIR . '/Sqldata';
		$mask = file_mode_info($path);
		if ($mask === false) {
			$warning = sprintf(L('dir_not_exist'), $path);
			$this->assign('warning', $warning);
		} elseif ($mask != 15) {
			$warning = sprintf(L('dir_priv'), $path);
			if (($mask&1) < 1) {
			$warning .= L('cannot_read') . '&nbsp;&nbsp;';
			}
			if (($mask&2) < 1) {
				$warning .= L('cannot_write') . '&nbsp;&nbsp;';
			}
			if (($mask&4) < 1) {
				$warning .= L('cannot_add') . '&nbsp;&nbsp;';
			}
			if (($mask&8) < 1) {
				$warning .= L('cannot_modify');
			}
			$this->assign('warning', $warning);
		} else {
			import("@.ORG.Sql");
		    /* 获取文件列表 */
			$real_list = array();
			$folder = opendir($path);
			while ($file = readdir($folder)) {
				if (strpos($file,'.sql') !== false) {
					$real_list[] = $file;
				}
			}
			natsort($real_list);
	
			$match = array();
			foreach ($real_list as $file) {
				if (preg_match('/_([0-9])+\.sql$/', $file, $match)) {
					if ($match[1] == 1) {
						$mark = 1;
					}else {
						$mark = 2;
					}
				}else {
					$mark = 0;
				}
	
				$file_size = filesize($path ."/". $file);
				$info = Sql::getHead($path ."/". $file);
				$list[] = array('name' => $file, 'ver' => $info['nblog_ver'], 'add_time' => $info['date'], 'vol' => $info['vol'], 'file_size' => num_bitunit($file_size), 'mark' => $mark);
			}
		}
		//print_r($list);
		$this->assign('action_link', array('href'=>__URL__.'/backup/', 'text' => L('backup')));
		$this->assign('ur_here',L('restore'));
		$this->assign('list',$list);
		$this->display();
	}
	
	//删除数据库文件
	public function remove() {	
		$this->checkLimits();
		if ($_REQUEST['delSql']) {	
			//print_r($_POST['chkvalue']);
			if (isset($_POST['chkvalue'])) {
			
				$m_file = array(); //多卷文件
				$s_file = array(); //单卷文件
		
				$path = ROOT_PATH . DATA_DIR . '/Sqldata/';
		
				foreach ($_POST['chkvalue'] as $file) {
					if (preg_match('/_[0-9]+\.sql$/', $file)) {
						$m_file[] = substr($file, 0, strrpos($file, '_'));
					} else {
						$s_file[] = $file;
					}
				}
		
				if ($m_file) {
					$m_file = array_unique ($m_file);
		
					// 获取文件列表 
					$real_file = array();
		
					$folder = opendir($path);
					while ($file = readdir($folder)) {
						if ( preg_match('/_[0-9]+\.sql$/', $file) && is_file($path . $file)) {
							$real_file[] = $file;
						}
					}
		
					foreach ($real_file as $file) {
						$short_file = substr($file, 0, strrpos($file, '_'));
						if (in_array($short_file, $m_file)) {
							@unlink($path . $file);
						}
					}
				}
		
				if ($s_file) {
					foreach ($s_file as $file) {
						@unlink($path . $file);
					}
				}
				
				set_log('drop(Sql)');
				$this->assign('jumpUrl',__URL__.'/restore/');
				$this->success (L('success'));
			}		
		} else {
			$this->error (L('illegal'));
		}
	}
	
	//数据恢复
	public function import() {
		$this->checkLimits();
		if ($_REQUEST['act']) {
			$file_name = empty($_GET['f']) ? '': trim($_GET['f']);
			$path = ROOT_PATH . DATA_DIR . '/Sqldata/';
				
			import("@.ORG.Sql");	
			$dump = new Sql ();
			
			if (preg_match('/_[0-9]+\.sql$/', $file_name)) {
				//多卷
				$short_name = substr($file_name, 0, strrpos($file_name, '_'));

				// 获取文件列表 
				$real_file = array();
				$folder = opendir($path);
				while ($file = readdir($folder)) {
					if (is_file($path . $file) && preg_match('/_[0-9]+\.sql$/', $file)) {
						$real_file[] = $file;
					}
				}
		
				// 所有相同分卷数据列表 
				$post_list = array();
				foreach ($real_file as $file) {
					$tmp_name = substr($file, 0, strrpos($file, '_'));
					if ($tmp_name == $short_name) {
						$post_list[] = $file;
					}
				}
		
				natsort($post_list);
		
				// 开始恢复数据 
				foreach ($post_list as $file) {
					$info = $dump->getHead($path . $file_name);
					if ($info['nblog_ver'] != VERSION ) {
						$this->error(sprintf(L('version_error'), VERSION, $info['nblog_ver']));
					}
					if (!$dump->sqlImport($path . $file)) {
						$this->error(L('sqlfile_error'));
					}
				}
				clear_cache_files(); //清除缓存
				set_log('restore(Sql, Date: '.$info['date'].')');
				$this->assign('jumpUrl',__URL__.'/restore/');
				$this->success (L('success'));
			
			} else {
			     // 单卷
				$info = $dump->getHead($path . $file_name);
				if ($info['nblog_ver'] != VERSION ) {
					$this->error(sprintf(L('version_error'), VERSION, $info['nblog_ver']));
				}
				if ($dump->sqlImport($path . $file_name)) {
					clear_cache_files(); //清除缓存
					set_log('restore(Sql, Date: '.$info['date'].')');
					$this->assign('jumpUrl',__URL__.'/restore/');
					$this->success (L('success'));
				} else {
					$this->error(L('sqlfile_error'));
				}
			}
		} else {
			$this->error (L('illegal'));
		}
	}
	
	//数据表优化
	public function optimize() {
		$db = M();
		$db_ver = $db->query('select version();');
		$db_ver = $db_ver[0]['version()'];
		$table  = $this->getTables();
		for ($i=0; $i<count($table); $i++) {
			$res[]    = $db->query("SHOW TABLE STATUS LIKE '" .$table[$i] . "%'");
			$status[] = $db->query('CHECK TABLE '.$table[$i]);
		}
		//echo "<pre>";
		//print_r($res);
		//echo "</pre>";
		for ($i=0; $i<count($res); $i++) {
			$type = $db_ver >= '4.1' ? $res[$i][0]['Engine'] : 'Type';
			$charset = $db_ver >= '4.1' ? $res[$i][0]['Collation'] : 'N/A';  
			$num += $res[$i][0]['Data_free'];  
			$res_list[$i]['Name']        = $res[$i][0]['Name'];
			$res_list[$i]['Type']        = $type;
			$res_list[$i]['Rows']        = $res[$i][0]['Rows'];
			$res_list[$i]['Data_length'] = sprintf(" %.2f KB", $res[$i][0]['Data_length'] / 1024);
			$res_list[$i]['Data_free']   = $res[$i][0]['Data_free'];
			$res_list[$i]['Charset']     = $charset;
			$res_list[$i]['Create_time'] = $res[$i][0]['Create_time'];
			$res_list[$i]['Update_time'] = $res[$i][0]['Update_time'];
			$res_list[$i]['Msg_text']    = $status[$i][0]['Msg_text'];
		}	
		//echo "<pre>";		
		//print_r($res_list);
		//echo "</pre>";
		
		$this->assign('ur_here',L('optimize'));
		$this->assign('num',$num);
		$this->assign('res_list',$res_list);
		$this->display();
	}
	
	//数据表优化
	public function runOptimize() {
		$this->checkLimits();	
		if ($_REQUEST['run']) {
			$db = M();
			$table  = $this->getTables();
			foreach ($table as $name) {
				if (isset($name)) {
					//$msg .='正在优化表: '.$name;
					$res = $db->query('optimize TABLE '.$name);
					/* 优化出错，尝试修复 */
					if ($res[0]['Msg_type'] =='error' && strpos($res[0]['Msg_text'], 'repair') !== false) {
						$db->query('REPAIR TABLE ' . $name);
					}
					/*if ($res) {
						$msg .= ' .........................................完成<br>';
					} else {
						$msg .= ' <font color=\"red\"><b>失败</b></font>';
					}*/
				}
			}
			$msgg .= L('optimize_ok').$_POST['num'];
			set_log('optimize(Sql, Overhead: '.$_POST["num"].')');
			$this->assign('jumpUrl',__URL__.'/optimize/');
			$this->success ($msgg);		
		} else {
			$this->error (L('illegal'));
		}
	}
	
	/**
     +----------------------------------------------------------
     * 取得数据库的表信息
     +----------------------------------------------------------
     * @access public
     +----------------------------------------------------------
     */
	public function getTables() {
		$sql = 'SHOW TABLES FROM '.C('DB_NAME');
		$db = M();
		$result = $db->query($sql);
		$info   =   array();
		foreach ($result as $val) {
			if(substr(current($val),0,strlen(C('DB_PREFIX'))) == C('DB_PREFIX')) { 
				$info[] = current($val);
			}	
		}
		return $info;
	}
	
}

?>